import re
from venv import logger

from django.contrib.auth.mixins import *
from django.shortcuts import reverse
from random import randint

from django.http import *
from django.shortcuts import *
from django.views import View
# 导入图片验证库
from django_redis import get_redis_connection

from libs.captcha.captcha import captcha
from libs.yuntongxun.sms import CCP
# 注册
from utils.response_code import RETCODE
from users.models import User
from django.contrib.auth import login
from django.contrib.auth import *

class RegisterView(View):
    def get(self,request):
        return  render(request,'register.html')
    def post(self,request):
        # 1.接收用户数据
        mobile=request.POST.get('mobile')
        password = request.POST.get('password')
        password2=request.POST.get('password2')
        sms_code = request.POST.get('sms_code')
        # 2.验证数据
        # 2-1.参数是否齐全
        if not all([mobile,password,password2,sms_code]):
            return HttpResponseBadRequest('参数不全')
        # 2-2手机号格式是否正确
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return HttpResponseBadRequest('手机号码格式不正确')
        # 2-3密码是否符合格式
        if not re.match(r'^[0-9a-zA-Z]{8,20}$',password) or not re.match(r'^[0-9a-zA-Z]{8,20}$',password2):
            return HttpResponseBadRequest('密码长度，格式不正确。长度8-20，必须是数字，字母')
        # 2-4.密码和确认密码是否一致
        if password != password2:
            return HttpResponseBadRequest('俩次输入的密码不一致')
        # 获取redis中的短信验证码
        redis_conn=get_redis_connection()
        redis_sms_code=redis_conn.get('sms:%s' % mobile)
        if redis_sms_code.decode() != sms_code:
            return HttpResponseBadRequest('短信验证码错误')
        # 3.保存注册信息
        user = User.objects.create_user(username=mobile,mobile=mobile,password=password)
        login(request,user)
        resp = redirect(reverse('home:index'))
        resp.set_cookie('is_login',True)
        resp.set_cookie('login_name',user.username)
        return resp

# 图片验证码
class ImageView(View):
    def get(selfself,request):
        '''
                      步骤：
                      1、接收前端传递过来的uuid
                      2、判断uuid失分获取到
                      3、通过调用captcha来生成图片验证码（返回：图片内容和图片二进制）
                      4、将图片内容保存到redis中。uuid作为key，图片内容作为值，同时还需要设置一个过期时间
                      5、返回图片给前端
                      :param request:
                      :return:
              '''
        uuid = request.GET.get('uuid')
        if uuid is None:
            return HttpResponse('uuid不存在')
        txt,image = captcha.generate_captcha()
        redis_conn = get_redis_connection('default')
        redis_conn.setex(name='img:%s' % uuid,time=300,value=txt)
        return HttpResponse(image,content_type='image/jpeg')
        pass


class SmsCodeView(View):
    def get(self,request):
        # 1.接收参数
        mobile=request.GET.get('mobile')
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('uuid')
        # 2.参数校验
        # 2.1验证参数是否齐全
        if not all([mobile,image_code,uuid]):
            return JsonResponse({'code':RETCODE.NECESSARYPARAMERR,"errmsg":'参数不全'})
        # 2-2
        redis_conn=get_redis_connection()
        # 从redis中获取已经存入的图片验证信息
        image_code_redis=redis_conn.get('img:%s' % uuid)
        if image_code_redis is None:
            return JsonResponse({'code':RETCODE.IMAGECODEERR,"errmsg":'图片验证码不存在'})
        # 删除redis中已经验证的图片验证码
        redis_conn.delete('img:%s' % uuid)
        # 从redis中取出的数据需要解码.docode（）
        if image_code != image_code_redis.decode().lower():
            return JsonResponse({'code':RETCODE.IMAGECODEERR,"errmsg":'图片验证码错误'})
        # 3.生成短信验证码，生成6位验证码
        sms_code = '%06d' % randint(0,999999)
        ccp=CCP()
        ccp.send_template_sms('15229112286',[sms_code,5],1)
        print(f'你的验证码是：{sms_code}')
        # 4、保存短信验证码内容到redis中,保存时间1分钟
        redis_conn.setex('sms:%s' % mobile, 60, sms_code)
        return JsonResponse({'code':RETCODE.OK,"errmsg":'短信发送成功'})

class LoginView(View):
    def get(self,request):
        return render(request,'login.html')

    def post(self, request):
        '''
               实现思路：
               1、接收提交参数
               2、验证参数
                2-1、手机号码是否符合规则
                2-2、密码是否符合规则
               3、用户认证登录
               4、状态保持
               5、根据用户选择的是否记住登录状态进行判断
               6、设置cookie信息，为首页显示服务
               7、跳转到首页
               :param request:
               :return:
               '''
        # 1、接收提交参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        remember = request.POST.get('remember')
        # 2、验证参数
        if not all([mobile, password]):
            return render(request, 'login.html', {'msg': '参数不齐全'})
            # 2-1、手机号码是否符合规则
        if not re.match('^1[3-9]\d{9}$', mobile):
            return render(request, 'login.html', {'msg': '手机号格式不正确'})
            # 2-2、密码是否符合规则
        if not re.match('^[a-z0-9A-Z]{8,20}$', password):
            return render(request, 'login.html', {'msg': '密码格式不正确'})
        # 3、用户认证登录
        # 使用django系统自带的用户认证代码将会返回一个user对象，如果账号密码正确，那么就返回该对象，否则返回None
        return_user = authenticate(mobile=mobile, password=password)
        if return_user is None:
            return render(request,'login.html',{'msg':'账号或密码错误'})
        # 4、状态保持
        login(request, return_user)

        # 5、根据用户选择的是否记住登录状态进行判断
        next_page=request.GET.get('next')
        if next_page:
            resp = redirect(next_page)
        else:
            resp = redirect(reverse('home:index'))
        if remember != 'on':  # 用户未勾选
            request.session.set_expiry(0)  # 当浏览器关闭后，清空session
            resp.set_cookie('is_login', True)
            u = json.dumps(return_user.username)
            resp.set_cookie('login_name', u)
        else:  # 用户勾选
            request.session.set_expiry(None)  # 设置session的过期时常时间为默认值，默认值时间为两周
            resp.set_cookie('is_login', True, max_age=14 * 24 * 3600)
            u = json.dumps(return_user.username)
            resp.set_cookie('login_name', u, max_age=14 * 24 * 3600)
        return resp
        # 6、设置cookie信息，为首页显示服务

        # 7、跳转到首页
        return HttpResponse('ok')

class LogoutView(View):
    def get(self, request):
        '''
        实现思路：
        1、清楚session数据
        2、删除cookie数据
        3、跳转到首页
        :param request:
        :return:
        '''
        # 实现思路：
        # 1、清楚session数据
        logout(request)
        # 2、删除cookie数据
        resp = redirect(reverse('home:index'))
        resp.delete_cookie('is_login')
        resp.delete_cookie('login_name')
        # 3、跳转到首页
        return resp

class ForgetPasswordView(View):

    def get(self, request):
        return render(request, 'forget_password.html')
    def post(self, request):
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        smscode = request.POST.get('sms_code')

        # 判断参数是否齐全
        if not all([mobile, password, password2, smscode]):
            return render(request,'forget_password.html',{'msg':'参数不全'})

        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号码')

        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseBadRequest('请输入8-20位的密码')

        # 判断两次密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')

        # 验证短信验证码
        redis_conn = get_redis_connection('default')
        sms_code_server = redis_conn.get('sms:%s' % mobile)
        if sms_code_server is None:
            return HttpResponseBadRequest('短信验证码已过期')
        if smscode != sms_code_server.decode():
            return HttpResponseBadRequest('短信验证码错误')

        # 根据手机号查询数据
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果该手机号不存在，则注册个新用户
            try:
                User.objects.create_user(username=mobile, mobile=mobile, password=password)
            except Exception:
                return HttpResponseBadRequest('修改失败，请稍后再试')
        else:
            # 修改用户密码
            user.set_password(password)
            user.save()

        # 跳转到登录页面
        response = redirect(reverse('users:login'))

        return response

#用户中心
class UserCenterView(LoginRequiredMixin,View):
    def get(self, request):
        # LoginRequiredMixin使用方法：
        # 1、待验证的视图需要继承该类即可，它会自动验证身份信息
        # 2、如果用户未登录，那么就是匿名用户，当访问该视图时，会自动进行跳转到默认登录地址：accounts / login /?next = / u
        # 3、我们需要在setting.py中配置默认登录地址即可
        # 4、在登录视图的post方法中，判断next有值跳转

        # 获取已经登录用户的信息
        userinfo = request.user
        context = {
        'username': userinfo.username,
        'mobile': userinfo.mobile,
        'avatar': userinfo.avatar.url if userinfo.avatar else None,
        'user_desc': userinfo.user_desc
        }
        return render(request, 'usercenter.html', context=context)

    # get 省略
    def post(self, request):
        '''
        实现思路：
        1、接收用户参数
        2、将用户参数更新到数据库
        3、更新cookie中的username
        4、刷新当前页面（重定向操作）
        5、返回相应
        :param request:
        :return:
        '''
        # 获取已经登录用户的信息
        userinfo = request.user
        # 1、接收用户参数
        # 获取用户提交的用户名，如果没有就将已登录的用户名赋值
        username = request.POST.get('username', userinfo.username)
        # 获取用户提交的介绍，如果没有就将已登录的介绍赋值
        user_desc = request.POST.get('desc', userinfo.user_desc)
        # 获取用户头像(如果没有图片保存地址，则会默认保存到项目的根目录下。否则需要在settting中进行配置地址
        avatar = request.FILES.get('avatar')
        # 2、将用户参数更新到数据库
        try:
            userinfo.username = username
            userinfo.user_desc = user_desc
            if avatar:
                userinfo.avatar = avatar
            userinfo.save()
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('修改用户信息失败')
        # 3、更新cookie中的username
        # 4、刷新当前页面（重定向操作）
        resp = redirect(reverse('home:index'))
        u = json.dumps(userinfo.username)
        resp.set_cookie('login_name', u)
        # 5、返回相应
        return resp

import json
from home.models import *
class WriteBlogView(View):
    def get(self,request):
        list=ArticleCategory.objects.all()
        return render(request,'writeblog.html',locals())

    def post(self, request):
        avatar = request.FILES.get('avatar')
        title = request.POST.get('title')
        category_id = request.POST.get('category')
        tags = request.POST.get('tags')
        sumary = request.POST.get('sumary')
        content = request.POST.get('content')
        user = request.user
        print([avatar, title, category_id, sumary, content])
        # 2、验证数据
        # 2-1、参数齐全验证
        if not all([avatar, title, category_id, sumary, content]):
            return HttpResponseBadRequest('参数不齐全')
        # 2-2、判断分类id
        try:
            category = ArticleCategory.objects.filter(pk=category_id).first()
        except ArticleCategory.DoesNotExist:
            return HttpResponseBadRequest('没有该分类信息')
        # 3、数据入库
        try:
            Article.objects.create(
                author=user,
                avatar=avatar,
                category=category,
                tags=tags,
                sumary=sumary,
                content=content,
                title=title,
            )
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('发布失败，请稍后重试')
        # 4、跳转到指定页面
        return redirect(reverse('home:index'))

